package main;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JFrame;

import model.Executable;
import model.GameClock;
import model.Model;
import model.entity.Avatar;
import model.entity.NPC;
import model.entity.Occupation;
import model.entity.brain.PetBrain;
import model.entity.stats.Stat;
import model.entity.stats.StatSet;
import model.entity.stats.StatType;
import model.entity.stats.StatWithMax;
import model.handler.AreaEffectHandler;
import model.handler.DeathHandler;
import model.interactionhandler.InteractionContainer;
import model.item.EquippedInventory;
import model.item.Inventory;
import model.map.Direction;
import model.map.FogOfWar;
import model.map.GameMap;
import model.map.HexLocationProjection;
import model.map.Location;
import model.map.MovementType;
import model.map.World;
import view.DirectionalModelToImage;
import view.EquipmentOverlay;
import view.GameButtonRegistry;
import view.GameWindow;
import view.InteractionOverlay;
import view.InventoryListProvider;
import view.ListOverlay;
import view.ListProvider;
import view.MainMenuOverlay;
import view.MapOverlay;
import view.ModelToImage;
import view.OverlayIds;
import view.StatsOverlay;
import controller.AvatarController;
import controller.CameraController;
import controller.EquipmentController;
import controller.GameConfig;
import controller.InteractionController;
import controller.InventoryController;
import controller.MainMenuController;

public class RunGame {
	
	public static void main(String args[]) {
		testGrid();
//		testGameClock();
//		testEquipmentOverlay();
	}
	
	public static void testEquipmentOverlay() {
		EquipmentOverlay eo = new EquipmentOverlay( new Dimension(800,600), null, 
				new Point(200,200), null);
		
		GameWindow gw = new GameWindow("AlejandroTests");
		gw.addOverlay( "testMapOverlay", eo );
		gw.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		gw.setSize( 800, 600 );
		gw.addMouseListener( GameButtonRegistry.getInstance() );
		gw.setVisible(true);
	}
	
	public static void testGrid() {
		
		Avatar avatar = createDummyAvatar();
		World.getInstance().setPlayer(avatar);
		
		GameMap gm = new GameMap("GameMap");
		World.getInstance().addMap( gm );
		World.getInstance().setCurrentMap( gm );
		gm.addEntity( avatar );
		FogOfWar fow = new FogOfWar( gm, avatar, new HexLocationProjection());
		
		World.getInstance().setPlayer( avatar );
		
		List<MovementType> movtyps = new ArrayList<MovementType>();
		movtyps.add(MovementType.GRASS);
		movtyps.add(MovementType.WATER);
		StatSet stats = new StatSet();
		
		stats.addStat(StatType.MOVEMENTSPEED, new Stat(10, StatType.MOVEMENTSPEED));
		stats.addStat(StatType.SIGHTRANGE, new Stat(5, StatType.SIGHTRANGE ));
		stats.addStat(StatType.HP, new Stat(100, StatType.HP));
		
		NPC pet = new NPC("Pet", Direction.S, new Location(11,13), stats, movtyps, new Inventory(), new EquippedInventory(), new Occupation(), false, null);
        pet.setBrain( new PetBrain( World.getInstance().getPlayer(), pet, World.getInstance().getCurrentMap()) );
        World.getInstance().getCurrentMap().addEntity(pet);
  
		
		MapOverlay mo = new MapOverlay( new Dimension(800,600), gm, new Location(13,13) );
		InteractionOverlay io = new InteractionOverlay( new Dimension(800,600), InteractionContainer.getInstance() );
		loadTestImages();//loads images into ModelToImage classes
		
		GameWindow gw = new GameWindow("AlejandroTests");
		gw.setSize( 800, 600 );
		gw.addOverlay( "testMapOverlay", mo );
		gw.addOverlay( "testInteractionoverlay", io);
		
		StatsOverlay sl = new StatsOverlay(gw.getSize(), avatar, new Point(20, 20), 30);
        gw.addOverlay(OverlayIds.STATS, sl);
		
        ListProvider inventoryListProvider = new InventoryListProvider(avatar.getInventory());
		InventoryController inventoryController = new InventoryController(avatar, inventoryListProvider);
		ListOverlay inventoryListOverlay = new ListOverlay(gw.getSize(), inventoryListProvider, 10, 400, 540);
		gw.addOverlay(OverlayIds.LIST, inventoryListOverlay);
        
		
		EquipmentOverlay eo = new EquipmentOverlay( new Dimension(800,600), avatar, new Point(27, 85), new HashMap<Model,MouseListener>() );
        EquipmentController ec = new EquipmentController( avatar, eo );
        gw.addOverlay(OverlayIds.EQUIP, eo);
		
		initializeRefresh( gw );
		
		CameraController cc = new CameraController( mo, gw );
		AvatarController ac = new AvatarController( avatar, gw, mo, InteractionContainer.getInstance());
		InteractionController ic = new InteractionController( io, gw, InteractionContainer.getInstance());
		
		gw.addMouseListener( GameButtonRegistry.getInstance() );
		
		gw.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		gw.setVisible(true);
		
		World.getInstance().getCurrentMap().getFogOfWar().update();
		
		GameConfig.GAME_WINDOW = gw;
		
		DeathHandler.getInstance().start();
		AreaEffectHandler.getInstance().start();
		
		MainMenuOverlay mmo = new MainMenuOverlay(new Dimension(800,600));
		MainMenuController mmc = new MainMenuController(mmo);
		gw.addOverlay( OverlayIds.MAIN_MENU, mmo);
		

	}
	
	public static Avatar createDummyAvatar() {
		ArrayList<MovementType> mt = new ArrayList<MovementType>();
		mt.add( MovementType.GRASS );
		mt.add( MovementType.WATER );
		StatSet stats = new StatSet();
		stats.addStat(StatType.MOVEMENTSPEED, new Stat(1, StatType.MOVEMENTSPEED));
		stats.addStat(StatType.SIGHTRANGE, new Stat(5, StatType.SIGHTRANGE));
		stats.addStat(StatType.HP, new StatWithMax(2000, StatType.HP, 2000));
        stats.addStat(StatType.MP, new StatWithMax(2000, StatType.MP, 2000));
        stats.addStat(StatType.PICKPOCKET, new Stat(90, StatType.PICKPOCKET));
        stats.addStat(StatType.LIVES, new Stat(1, StatType.LIVES));
        
        EquippedInventory ei = new EquippedInventory();
        
		Avatar avatar = new Avatar("entity", Direction.S, new Location(11,11), stats, mt , new Inventory(), ei, null, false);
		return avatar;
	}
	
	public static void initializeRefresh( final GameWindow gw ) {
		GameClock.getInstance().scheduleAtFixedRate( 1, new Executable() {
			@Override
			public void execute() {
				gw.repaint();
			}
		} );
	}
	
	public static void loadTestImages() {
		ModelToImage.addImage( "Unpassable", "./Data/imgs/grayTile.png" );
		ModelToImage.addImage( "Grass", "./Data/imgs/greenTile.png" );
		ModelToImage.addImage( "obstacle", "./Data/imgs/obstacle.png" );
		ModelToImage.addImage( "areaEffect", "./Data/imgs/areaEffect.png" );
		ModelToImage.addImage( "decal", "./Data/imgs/decal.png" );
		ModelToImage.addImage( "item", "./Data/imgs/item.png" );
		ModelToImage.addImage( "Water", "./Data/imgs/waterTile.png");
		ModelToImage.addImage( "redTile", "./Data/imgs/redTile.png" );
		ModelToImage.addImage( "Tree", "./Data/imgs/TreeObstacle.png");
		ModelToImage.addImage( "ThunderStaff", "./Data/imgs/ThunderStaff.png");
		ModelToImage.addImage( "LongbowRanged", "./Data/imgs/LongbowRanged.png");
		ModelToImage.addImage( "Axe1H", "./Data/imgs/Axe1H.png");
		ModelToImage.addImage( "slimePotion", "./Data/imgs/SlimeNPC.png");
		ModelToImage.addImage( "damage_ae", "./Data/imgs/damage_ae.png");
		//add entity
		Map<Direction, String> m0 = new HashMap<Direction, String>();
		m0.put(Direction.S, "./Data/imgs/avatar_s.png");
		m0.put(Direction.SE, "./Data/imgs/avatar_se.png");
		m0.put(Direction.SW, "./Data/imgs/avatar_sw.png");
		m0.put(Direction.N, "./Data/imgs/avatar_n.png");
		m0.put(Direction.NE, "./Data/imgs/avatar_ne.png");
		m0.put(Direction.NW, "./Data/imgs/avatar_nw.png");
		DirectionalModelToImage.addImage("entity", m0);
		
		Map<Direction, String> e1 = new HashMap<Direction, String>();
		e1.put(Direction.S, "./Data/imgs/satan_s.png");
		e1.put(Direction.SE, "./Data/imgs/satan_se.png");
		e1.put(Direction.SW, "./Data/imgs/satan_sw.png");
		e1.put(Direction.N, "./Data/imgs/satan_n.png");
		e1.put(Direction.NE, "./Data/imgs/satan_ne.png");
		e1.put(Direction.NW, "./Data/imgs/satan_nw.png");
		DirectionalModelToImage.addImage("entity1", e1);
		
		Map<Direction, String> o1 = new HashMap<Direction, String>();
		o1.put(Direction.S, "./Data/imgs/octopus.png");
		o1.put(Direction.SE, "./Data/imgs/octopus.png");
		o1.put(Direction.SW, "./Data/imgs/octopus.png");
		o1.put(Direction.N, "./Data/imgs/octopus.png");
		o1.put(Direction.NE, "./Data/imgs/octopus.png");
		o1.put(Direction.NW, "./Data/imgs/octopus.png");
		DirectionalModelToImage.addImage("octopus", o1);
		
		Map<Direction, String> v1 = new HashMap<Direction, String>();
		v1.put(Direction.S, "./Data/imgs/vehicle_s.png");
		v1.put(Direction.SE, "./Data/imgs/vehicle_se.png");
		v1.put(Direction.SW, "./Data/imgs/vehicle_sw.png");
		v1.put(Direction.N, "./Data/imgs/vehicle_n.png");
		v1.put(Direction.NE, "./Data/imgs/vehicle_ne.png");
		v1.put(Direction.NW, "./Data/imgs/vehicle_nw.png");
		DirectionalModelToImage.addImage("sk8board", v1);
		
		Map<Direction, String> m3 = new HashMap<Direction, String>();
		m3.put(Direction.S, "./Data/imgs/Pet.png");
		m3.put(Direction.SE, "./Data/imgs/Pet.png");
		m3.put(Direction.SW, "./Data/imgs/Pet.png");
		m3.put(Direction.N, "./Data/imgs/Pet.png");
		m3.put(Direction.NE, "./Data/imgs/Pet.png");
		m3.put(Direction.NW, "./Data/imgs/Pet.png");
		DirectionalModelToImage.addImage("Pet", m3);
		
		//add vehicle
		Map<Direction, String> m1 = new HashMap<Direction, String>();
		m1.put(Direction.S, "./Data/imgs/vehicle.png");
		DirectionalModelToImage.addImage("vehicle", m1);
		//add projectile
		ModelToImage.addImage( "projectile", "./Data/imgs/projectile.png" );
		
		//add semitransparent tile
		ModelToImage.addImage( "semitransparentTile", "./Data/imgs/semitransparentHexagon.png" );
		ModelToImage.addImage( "TalkButton", "./Data/imgs/TalkButton.png" );
		ModelToImage.addImage( "MountButton", "./Data/imgs/MountButton.png" );
		ModelToImage.addImage( "SummonerButton", "./Data/imgs/SummonerButton.png" );
		ModelToImage.addImage( "SmasherButton", "./Data/imgs/SmasherButton.png" );
		ModelToImage.addImage( "SneakButton", "./Data/imgs/SneakButton.png" );
	}

	public static void testGameClock() {
		final GameClock c = GameClock.getInstance();
		Log.out( Log.VIEW, "Before first executable.");
		final Executable e = new Executable() {
			@Override
			public void execute() {
				Log.out( Log.VIEW, "In first executable.");
			}
		};
		Executable e2 = new Executable() {
			@Override
			public void execute() {
				Log.out( Log.VIEW, "In second executable: remove first executable.");
				c.remove( e );
			}
		};
		c.scheduleAtFixedRate(80, e);
		c.schedule(410, e2);
	}
}
